{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# 打印所有单行变量\n",
    "from IPython.core.interactiveshell import InteractiveShell\n",
    "InteractiveShell.ast_node_interactivity = 'all'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 迭代\n",
    "\n",
    "在使用Python的过程中，很容易混淆如下几个关联的概念：\n",
    "\n",
    "* 容器(container)\n",
    "* 可迭代对象(Iterable)\n",
    "* 迭代器(Iterator)\n",
    "* 生成器(generator)\n",
    "* list, set, dict解析式\n",
    "* 生成器表达式"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 容器（container)\n",
    "\n",
    "容器是用来储存元素的一种数据结构，它支持隶属测试，容器将所有数据保存在内存中，在Python中典型的容器有：\n",
    "\n",
    "*   list， deque, ...\n",
    "*   set，frozesets，...\n",
    "*   dict, defaultdict, OrderedDict, Counter, ...\n",
    "*   tuple, namedtuple, ...\n",
    "*   str\n",
    "\n",
    "用in，not in判断是否存在，字典容器通过检查是否包含键来进行判断，字符串通过检查是否包含某个子串来判断\n",
    "> **注意**：并非所有的容器都是可迭代对象。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "1 in [1,2,3]      # -->\n",
    "4 in [1,2,3]      # -->\n",
    "4 not in [1,2,3]  # -->"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 可迭代对象\n",
    "\n",
    "正如前面所提到的，大部分容器都是可迭代的，但是还有其他一些对象也可以迭代，例如，文件对象以及管道对象等等"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "2"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "list"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "list_iterator"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x = [1,2,3]\n",
    "y = iter(x)\n",
    "\n",
    "next(y)  # -->\n",
    "next(y)  # -->\n",
    "\n",
    "type(x)  # -->\n",
    "type(y)  # -->"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "在这里，x是可迭代对象。而y是迭代器，可以从可迭代对象x中获取值。\n",
    "\n",
    "> **注意**：可迭代的类中，一般实现以下两个方法，`__iter__()`以及`__next()__`方法，`__iter__()`方法返回self。\n",
    "\n",
    "实际调用过程如下：\n",
    "\n",
    "![](http://upload-images.jianshu.io/upload_images/1677721-9453ca206b60475d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 迭代器(Iterators)\n",
    "* 迭代器是一个可以记住遍历的位置的对象。\n",
    "* 迭代器对象从第一个元素开始访问，直到所有的元素被访问完结束。\n",
    "* 迭代器只能往前不会后退。\n",
    "* 迭代器有两个基本的方法：`__iter__()` 和 `__next__()`"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### itertools模块"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "13"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "14"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from itertools import count\n",
    "counter = count(start=13)\n",
    "\n",
    "next(counter)  # -->\n",
    "next(counter)  # -->"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "无限序列："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'red'"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "'white'"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "'blue'"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "'red'"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from itertools import cycle\n",
    "colors = cycle([\"red\",\"white\",\"blue\"])\n",
    "\n",
    "next(colors)  # -->\n",
    "next(colors)  # -->\n",
    "next(colors)  # -->\n",
    "next(colors)  # -->"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "无限序列生成有限序列："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "red\n",
      "white\n",
      "blue\n",
      "red\n"
     ]
    }
   ],
   "source": [
    "from itertools import islice\n",
    "colors = cycle(['red', 'white', 'blue'])    # infinite\n",
    "limited = islice(colors, 0, 4)              # finite\n",
    "for x in limited:       # so safe to use for-loop on\n",
    "    print(x)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 生成器(generator)\n",
    "带有`yield`关键字的的函数在Python中被称之为 generator(生成器)。\n",
    "一个函数或者子程序都只能return一次，但是一个生成器能暂停执行并返回一个中间的结果。\n",
    "> 生成器其实就是一种特殊的迭代器\n",
    "\n",
    "生成器的另一个优点就是无须将对象的所有元素都存入内存之后，才开始进行操作。生成器仅在迭代至某个元素时才会将该元素放入内存，而在这之前或之后，元素可以不存在或者被销毁。这个特点使得它特别适合用于遍历一些巨大的或是无限的类序列对象，EG. 大文件/大集合/大字典/斐波那契数列等。这个特点被称为 延迟计算 或 惰性求值(Lazy evaluation)，可以有效的节省内存。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### list解析式\n",
    "```\n",
    "[expr for iter_var in iterable]    # 最终生成一个列表[expr]\n",
    "[expr for iter_var in iterable if cond_expr]\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[(1, 1), (1, 2), (1, 3), (2, 1), (2, 2), (2, 3)]"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x = [(x+1, y+1) for x in range(2) for y in range(3)] \n",
    "x"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[16, 17, 18, 19]"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y = [x+10 for x in range(10) if x>5]\n",
    "y"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> 还有集合解析，类似列表解析，区别在于结果满足集合的特性"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### dict解析式"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{1: 'a', 2: 'b', 3: 'c', 4: 'd'}"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x = {\"a\":1, \"b\":2, \"c\":3, \"d\":4}\n",
    "y = {v: k for k, v in x.items()}\n",
    "y"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 生成器表达式\n",
    "```\n",
    "(expr for iter_var in iterable)\n",
    "(expr for iter_var in iterable if cond_expr)\n",
    "```\n",
    "当序列过长，而每次只需要获取一个元素时，应当考虑使用生成器表达式而不是列表解析。生成器表达式的语法和列表解析一样，只不过生成器表达式是被`()`括起来的，而不是`[]`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<generator object <genexpr> at 0x7f75c84bfdb0>"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "18"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "19"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "ename": "StopIteration",
     "evalue": "",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mStopIteration\u001b[0m                             Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-11-5792f45bb622>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m      4\u001b[0m \u001b[0my\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__next__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m  \u001b[0;31m# -->\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      5\u001b[0m \u001b[0my\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__next__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m  \u001b[0;31m# -->\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 6\u001b[0;31m \u001b[0my\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__next__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m  \u001b[0;31m# --> 报错\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;31mStopIteration\u001b[0m: "
     ]
    }
   ],
   "source": [
    "y = (x+10 for x in range(10) if x>7)\n",
    "y  # -->\n",
    "\n",
    "y.__next__()  # -->\n",
    "y.__next__()  # -->\n",
    "y.__next__()  # >_< StopIteration"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "生成器表达式并不真正创建数字列表， 而是返回一个生成器，这个生成器在每次计算出一个条目后，把这个条目“产生”(yield)出来。 生成器表达式使用了“惰性计算”(lazy evaluation)，只有在检索时才被赋值 (evaluated)，所以在列表比较长的情况下使用内存上更有效。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 并行迭代\n",
    "迭代两个以上的集合\n",
    "\n",
    "### zip(iter1 [,iter2 [...]])\n",
    "\n",
    "#### 问题一：多个矩阵元素互换"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[(1, 4, 7), (2, 5, 8), (3, 6, 9)]"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "[(1, 2, 3), (4, 5, 6), (7, 8, 9)]"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x = [1, 2, 3]\n",
    "y = [4, 5, 6]\n",
    "z = [7, 8, 9]\n",
    "xyz = list(zip(x, y, z))\n",
    "xyz  # -->\n",
    "\n",
    "zyx = list(zip(*xyz))   # 参数加*解压\n",
    "zyx  # -->"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 问题二：列表求和\n",
    "有两个列表，分别是：a = [1, 2, 3, 4, 5], b = [9, 8, 7, 6, 5]，要计算这两个列表中对应元素的和。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[10, 10, 10, 10, 10]"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#方法一：\n",
    "a = [1, 2, 3, 4, 5]\n",
    "b = [9, 8, 7, 6, 5]\n",
    "c = []\n",
    "for i in range(len(a)):\n",
    "    c.append(a[i] + b[i])\n",
    "\n",
    "c"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[10, 10, 10, 10, 10]"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 方法二：\n",
    "d = []\n",
    "for x,y in zip(a,b):\n",
    "    d.append(x + y)\n",
    "\n",
    "d"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[10, 10, 10, 10, 10]"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "[10, 10, 10, 10, 10]"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 用列表解析：\n",
    "\n",
    "x = [a[i]+b[i] for i in range(len(a))]\n",
    "x  # -->\n",
    "\n",
    "y = [x+y for x,y in zip(a,b)]\n",
    "y  # -->"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 问题三：字典键值互换"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{1: 'a', 2: 'b', 3: 'c'}"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 用for循环:\n",
    "d = {'a':1, 'b':2, 'c':3}\n",
    "m = {}\n",
    "for k, v in d.items():\n",
    "    m[v] = k  # 以v为key,以k为values添加键值对\n",
    "\n",
    "m  # -->"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{1: 'a', 2: 'b', 3: 'c'}"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 因为字典有items方法,而zip只能获得key:\n",
    "x = dict(zip(d.values(),d.keys()))\n",
    "x  # -->"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{1: 'a', 2: 'b', 3: 'c'}"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 用dict解析:\n",
    "y = {v:k for k, v in d.items()}\n",
    "y  # -->"
   ]
  }
 ],
 "metadata": {
  "hide_input": false,
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.4rc1"
  },
  "toc": {
   "nav_menu": {},
   "number_sections": false,
   "sideBar": true,
   "skip_h1_title": false,
   "toc_cell": false,
   "toc_position": {
    "height": "839px",
    "left": "0px",
    "right": "1689px",
    "top": "107px",
    "width": "231px"
   },
   "toc_section_display": "block",
   "toc_window_display": true
  },
  "varInspector": {
   "cols": {
    "lenName": "15",
    "lenType": "10",
    "lenVar": "60"
   },
   "kernels_config": {
    "python": {
     "delete_cmd_postfix": "",
     "delete_cmd_prefix": "del ",
     "library": "var_list.py",
     "varRefreshCmd": "print(var_dic_list())"
    },
    "r": {
     "delete_cmd_postfix": ") ",
     "delete_cmd_prefix": "rm(",
     "library": "var_list.r",
     "varRefreshCmd": "cat(var_dic_list()) "
    }
   },
   "types_to_exclude": [
    "module",
    "function",
    "builtin_function_or_method",
    "instance",
    "_Feature"
   ],
   "window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
